#pragma once

#include <functional>
#include <stdexcept>
#include <thread>
#include <utility>

class Thread {
public:
  using ThreadFunc = std::function<void(int)>;

  explicit Thread(ThreadFunc func)
      : func_(std::move(func)), threadId_(generateID_++) {}

  ~Thread() {
    // if (worker_.joinable()) {
    //   worker_.join(); // worker_.join() 会崩溃?
    // }

    // “工作线程在自己的执行函数里直接从容器里删掉自己” 会导致析构时 join() 自己 → 程序崩溃。
    // 如果析构发生在当前线程上下文，改用 detach 避免自 join
    if (worker_.get_id() == std::this_thread::get_id()) {
      worker_.detach();
    } else {
      worker_.join();
    }
  }

  void start() {
    if (started_) {
      throw std::logic_error("Thread::start() called twice");
    }
    started_ = true;

    worker_ = std::thread([fn = std::move(func_), this]() mutable {
      if (fn) { // 检查 std::function<void(int)> 是否保存了有效的可调用对象
        fn(threadId_);
      }
    });
  }

  int getThreadID() const { return threadId_; }

private:
  ThreadFunc func_;
  std::thread worker_;
  bool started_{false}; // 防止同一个 Thread 对象被重复启动
  static int generateID_;
  int threadId_{0}; // 保存线程ID
};